package czStvDpds.mapeditor;

import czStvDpds.mapmanagment.Map;
import czStvDpds.mapmanagment.TilesInfo;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.*;

/**
 * Hlavní okno editoru
 *
 * @author Jirka
 */
public class MapEditorFrame extends JFrame {

    private static final int FRAME_SIZE_RESERVE = 200;

    public void start(Map map) {
        initFrame();
        initMapDisplay(map);
        initComponents();
        this.setVisible(true);
    }

    public void initFrame() {
        this.setTitle("DPDS Map editor");
        this.setSize(606, 655);
        this.setLocation(200, 15);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new BorderLayout());
        this.setResizable(false);
        this.addKeyListener(new MapEditorFrameKL());
    }
    MapDisplay mapDisplay;

    public void initMapDisplay(Map map) {
        DisplayMode currDisplayMode = getCurrentDisplayMode();
        float maxSize = Math.min(currDisplayMode.getWidth(), currDisplayMode.getHeight());
        float minSize = maxSize - FRAME_SIZE_RESERVE;
        int regionSize;
        if (map.getWidth() >= 30 && map.getHeight() >= 30) {
            regionSize = 30;
            for (int i = 1; true; i++) {
                if (regionSize * i > minSize) {
                    this.setSize((int) (regionSize * i) + 6, (int) (regionSize * i) + 55);
                    break;
                }
            }
        } else {
            regionSize = (int) Math.min(map.getWidth(), map.getHeight());
            for (int i = 1; true; i++) {
                if (regionSize * i > minSize) {
                    this.setSize((int) (regionSize * i) + 6, (int) (regionSize * i) + 55);
                    break;
                }
            }
        }
        Paintbrush paintbrush = new Paintbrush(TilesInfo.getTilesInfo().getTile(9), 0);
        mapDisplay = new MapDisplay(map, paintbrush, regionSize, regionSize, 0, 0, 1);
        mapDisplay.init();
        this.add(mapDisplay.getPanel(), BorderLayout.CENTER);
    }
    JPanel southPanel, southMidPanel, brushSizePanel, scrollSpeedPanel, toolsPanel;
    JButton saveButton, plusBrushSizeButton, minusBrushSizeButton,
            plusScrollSpeedButton, minusScrollSpeedButton, backButton,
            toolsButton;
    JLabel brushSizeLabel, scrollSpeedLabel;
    JComboBox selectTileComboBox;

    public void initComponents() {
        southPanel = new JPanel(new BorderLayout());
        this.add(southPanel, BorderLayout.SOUTH);

        // Výběr dlaždic
        selectTileComboBox = new JComboBox();
        selectTileComboBox.setMaximumRowCount(TilesInfo.getTilesInfo().getTilesNumber());
        selectTileComboBox.setFocusable(false);
        for (int i = 1; i <= TilesInfo.getTilesInfo().getTilesNumber(); i++) {
            selectTileComboBox.addItem(TilesInfo.getTilesInfo().getName(i));
        }
        selectTileComboBox.addItemListener(new SelectTileComboBoxIL());
        selectTileComboBox.setSelectedItem(TilesInfo.getTilesInfo().getName(mapDisplay.getPaintbrush().getPaintedTile().getId()));
        southPanel.add(selectTileComboBox, BorderLayout.WEST);

        // Tlačítko pro uložení
        saveButton = new JButton("Ulozit jako...");
        saveButton.setFocusable(false);
        saveButton.addActionListener(new SaveButtonAL());
        southPanel.add(saveButton, BorderLayout.EAST);

        // Další nástroje
        southMidPanel = new JPanel(new BorderLayout());
        southPanel.add(southMidPanel, BorderLayout.CENTER);

        brushSizePanel = new JPanel(new BorderLayout(10, 0));
        southMidPanel.add(brushSizePanel, BorderLayout.WEST);
        plusBrushSizeButton = new JButton("+");
        plusBrushSizeButton.setFocusable(false);
        plusBrushSizeButton.addActionListener(new PlusBrushSizeButtonAL());
        brushSizePanel.add(plusBrushSizeButton, BorderLayout.WEST);
        brushSizeLabel = new JLabel("" + (mapDisplay.getPaintbrush().getSize() + 1), JLabel.CENTER);
        brushSizePanel.add(brushSizeLabel, BorderLayout.CENTER);
        minusBrushSizeButton = new JButton("-");
        minusBrushSizeButton.setFocusable(false);
        minusBrushSizeButton.addActionListener(new MinusBrushSizeButtonAL());
        brushSizePanel.add(minusBrushSizeButton, BorderLayout.EAST);

        scrollSpeedPanel = new JPanel(new BorderLayout(10, 0));
        southMidPanel.add(scrollSpeedPanel, BorderLayout.EAST);
        plusScrollSpeedButton = new JButton("+");
        plusScrollSpeedButton.setFocusable(false);
        plusScrollSpeedButton.addActionListener(new PlusScrollSpeedButtonAL());
        scrollSpeedPanel.add(plusScrollSpeedButton, BorderLayout.WEST);
        scrollSpeedLabel = new JLabel("" + mapDisplay.getScrollingSpeed(), JLabel.CENTER);
        scrollSpeedPanel.add(scrollSpeedLabel, BorderLayout.CENTER);
        minusScrollSpeedButton = new JButton("-");
        minusScrollSpeedButton.setFocusable(false);
        minusScrollSpeedButton.addActionListener(new MinusScrollSpeedButtonAL());
        scrollSpeedPanel.add(minusScrollSpeedButton, BorderLayout.EAST);

        toolsPanel = new JPanel(new BorderLayout());
        southMidPanel.add(toolsPanel, BorderLayout.CENTER);
        toolsButton = new JButton("Tools");
        toolsButton.setFocusable(false);
        //toolsButton.addActionListener(new ToolsButtonAL());
        toolsPanel.add(toolsButton, BorderLayout.CENTER);
        backButton = new JButton("Zpět");
        backButton.setFocusable(false);
        //backButton.addActionListener(new BackButtonAL());
        toolsPanel.add(backButton, BorderLayout.EAST);
    }

    public void debugPrint() {
        System.out.println(mapDisplay.getPanel().getWidth() + ", " + this.getWidth());
        System.out.println(mapDisplay.getPanel().getHeight() + ", " + this.getHeight());
    }

    /**
     * Vrátí současný mód obrazovky
     *
     * @return
     */
    public DisplayMode getCurrentDisplayMode() {
        GraphicsEnvironment environment =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice device = environment.getDefaultScreenDevice();
        return device.getDisplayMode();
    }

    class PlusScrollSpeedButtonAL implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            mapDisplay.setScrollingSpeed(mapDisplay.getScrollingSpeed() + 1);
            scrollSpeedLabel.setText("" + mapDisplay.getScrollingSpeed());
        }
    }

    class MinusScrollSpeedButtonAL implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (mapDisplay.getScrollingSpeed() > 1) {
                mapDisplay.setScrollingSpeed(mapDisplay.getScrollingSpeed() - 1);
                scrollSpeedLabel.setText("" + mapDisplay.getScrollingSpeed());
            }
        }
    }

    class SaveButtonAL implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            new SaveAsFrame().start();
        }
    }

    class SaveAsFrame extends JFrame {

        public void start() {
            initSaveAsFrame();
            initSaveAsComponents();
            this.setVisible(true);
        }

        public void initSaveAsFrame() {
            this.setTitle("DPDS Map editor");
            this.setSize(550, 150);
            this.setLocation(350, 150);
            this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            this.setLayout(new GridLayout(3, 1));
        }
        JLabel saveAsLabel;
        JTextField saveAsTextField;
        JButton saveAsButton;

        public void initSaveAsComponents() {
            saveAsLabel = new JLabel("Název mapy v souboru \"resources\\maps\" bez koncovky \".txt\":", JLabel.CENTER);
            this.add(saveAsLabel);
            saveAsTextField = new JTextField("");
            saveAsTextField.addActionListener(new SaveAsButtonAL());
            this.add(saveAsTextField);
            saveAsButton = new JButton("Uložit");
            saveAsButton.setFocusable(false);
            saveAsButton.addActionListener(new SaveAsButtonAL());
            this.add(saveAsButton);
        }

        public void showMapWritingSuccesMessage() {
            JOptionPane.showMessageDialog(this, "Mapa úspěšně uložena,"
                    + " nezapomeň ale, že aby byla přístupná všem v SVN musíte"
                    + " jít do files v NetBeans a comittnout jí!", "Mapa uložena", JOptionPane.INFORMATION_MESSAGE);
        }

        public void showMapWritingExceptionMessage() {
            JOptionPane.showMessageDialog(this, "Nepodařilo se uložit mapu", "Chyba při ukládání mapy", JOptionPane.ERROR_MESSAGE);
        }

        class SaveAsButtonAL implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent e) {
                boolean worked = true;
                try {
                    writeMap(mapDisplay.getMap(), "resources/maps/" + saveAsTextField.getText() + ".txt");
                } catch (IOException ex) {
                    showMapWritingExceptionMessage();
                    worked = false;
                }
                if (worked) {
                    dispose();
                    showMapWritingSuccesMessage();
                }
            }
        }
    }

    public void writeMap(Map map, String fileName) throws IOException {
        String[][] mapStringArray = new String[map.getWidth()][map.getHeight()];
        for (int x = 0; x < map.getWidth(); x++) {
            for (int y = 0; y < map.getHeight(); y++) {
                if (map.getTile(x, y).getId() >= 1 && map.getTile(x, y).getId() <= 9) {
                    mapStringArray[x][y] = "" + map.getTile(x, y).getId();
                } else {
                    if (map.getTile(x, y).getId() == 10) { // docanse reseni
                        mapStringArray[x][y] = "s";
                    }
                }
            }
        }

        BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));

        for (int y = 0; y < mapStringArray[0].length; y++) {
            for (int x = 0; x < mapStringArray.length; x++) {
                writer.append(mapStringArray[x][y].charAt(0));
            }
            if (y < mapStringArray[0].length - 1) {
                writer.newLine();
            }
        }

        writer.close();
    }

    class PlusBrushSizeButtonAL implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (mapDisplay.getPaintbrush().getSize() + 1 < mapDisplay.getRegionWidth() / 2) {
                mapDisplay.getPaintbrush().setSize(mapDisplay.getPaintbrush().getSize() + 1);
                brushSizeLabel.setText("" + (mapDisplay.getPaintbrush().getSize() + 1)); // Přičítá se jedna protože min. velikost je 1, nikoli 0
                mapDisplay.repaintMouse();
            }
        }
    }

    class MinusBrushSizeButtonAL implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (mapDisplay.getPaintbrush().getSize() - 1 >= 0) {
                mapDisplay.getPaintbrush().setSize(mapDisplay.getPaintbrush().getSize() - 1);
                brushSizeLabel.setText("" + (mapDisplay.getPaintbrush().getSize() + 1)); // Přičítá se jedna protože min. velikost je 1, nikoli 0                
                mapDisplay.repaintMouse();
            }
        }
    }

    class SelectTileComboBoxIL implements ItemListener {

        @Override
        public void itemStateChanged(ItemEvent e) {
            for (int i = 1; i <= TilesInfo.getTilesInfo().getTilesNumber(); i++) {
                String name = TilesInfo.getTilesInfo().getName(i);
                if (name.equals(selectTileComboBox.getSelectedItem())) {
                    mapDisplay.getPaintbrush().setPaintedTile(TilesInfo.getTilesInfo().getTile(name));
                }
            }
        }
    }

    class MapEditorFrameKL extends KeyAdapter {

        public void keyPressed(KeyEvent e) {
            int code = e.getKeyCode();

            // testovani
            if (code == KeyEvent.VK_T) {
                debugPrint();
            }

            // zmena dlazidce pomoci klaves
            if (code >= 112 && code <= 121) {
                mapDisplay.getPaintbrush().setPaintedTile(TilesInfo.getTilesInfo().getTile(code - 111));
                selectTileComboBox.setSelectedIndex(code - 112);
                mapDisplay.repaintMouse();
            }

            // posouvani
            if (code == KeyEvent.VK_RIGHT) {
                if (mapDisplay.getRegionOffsetX() + mapDisplay.getRegionWidth() <= mapDisplay.getMap().getWidth() - mapDisplay.getScrollingSpeed()) {
                    mapDisplay.setRegionOffsetX(mapDisplay.getRegionOffsetX() + mapDisplay.getScrollingSpeed());
                    mapDisplay.updateTiles();
                } else {
                    for (int smoothScroll = mapDisplay.getScrollingSpeed() - 1; smoothScroll > 0; smoothScroll--) {
                        if (mapDisplay.getRegionOffsetX() + mapDisplay.getRegionWidth() <= mapDisplay.getMap().getWidth() - smoothScroll) {
                            mapDisplay.setRegionOffsetX(mapDisplay.getRegionOffsetX() + smoothScroll);
                            mapDisplay.updateTiles();
                        }
                    }
                }
                mapDisplay.repaintMouse();
            }
            if (code == KeyEvent.VK_LEFT) {
                if (mapDisplay.getRegionOffsetX() >= 0 + mapDisplay.getScrollingSpeed()) {
                    mapDisplay.setRegionOffsetX(mapDisplay.getRegionOffsetX() - mapDisplay.getScrollingSpeed());
                    mapDisplay.updateTiles();
                } else {
                    for (int smoothScroll = mapDisplay.getScrollingSpeed() - 1; smoothScroll > 0; smoothScroll--) {
                        if (mapDisplay.getRegionOffsetX() >= 0 + smoothScroll) {
                            mapDisplay.setRegionOffsetX(mapDisplay.getRegionOffsetX() - smoothScroll);
                            mapDisplay.updateTiles();
                        }
                    }
                }
                mapDisplay.repaintMouse();
            }
            if (code == KeyEvent.VK_DOWN) {
                if (mapDisplay.getRegionOffsetY() + mapDisplay.getRegionHeight() <= mapDisplay.getMap().getHeight() - mapDisplay.getScrollingSpeed()) {
                    mapDisplay.setRegionOffsetY(mapDisplay.getRegionOffsetY() + mapDisplay.getScrollingSpeed());
                    mapDisplay.updateTiles();
                } else {
                    for (int smoothScroll = mapDisplay.getScrollingSpeed() - 1; smoothScroll > 0; smoothScroll--) {
                        if (mapDisplay.getRegionOffsetY() + mapDisplay.getRegionHeight() <= mapDisplay.getMap().getHeight() - smoothScroll) {
                            mapDisplay.setRegionOffsetY(mapDisplay.getRegionOffsetY() + smoothScroll);
                            mapDisplay.updateTiles();
                        }
                    }
                }
                mapDisplay.repaintMouse();
            }
            if (code == KeyEvent.VK_UP) {
                if (mapDisplay.getRegionOffsetY() >= 0 + mapDisplay.getScrollingSpeed()) {
                    mapDisplay.setRegionOffsetY(mapDisplay.getRegionOffsetY() - mapDisplay.getScrollingSpeed());
                    mapDisplay.updateTiles();
                } else {
                    for (int smoothScroll = mapDisplay.getScrollingSpeed() - 1; smoothScroll > 0; smoothScroll--) {
                        if (mapDisplay.getRegionOffsetY() >= 0 + smoothScroll) {
                            mapDisplay.setRegionOffsetY(mapDisplay.getRegionOffsetY() - smoothScroll);
                            mapDisplay.updateTiles();
                        }
                    }
                }
                mapDisplay.repaintMouse();
            }
        }
    }
}